﻿using System;
using System.Collections.Specialized;
using System.Configuration;
using System.DirectoryServices;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Mailias.UI.Web.Models;

namespace Mailias.UI.Web.Controllers
{
    public class MessagesController : BaseDocumentStoreController
    {
        //
        // GET: /Messages/
        [HttpGet]
        public ActionResult Index()
        {
            var model = MessagesIndexViewModel.Create(DocumentSession);
            return View(model);
        }

        [HttpGet]
        public ActionResult UserMessages()
        {
            var model = MessagesIndexViewModel.CreateForUser(DocumentSession, CurrentUserName);

            return View(model);
        }

        [HttpGet]
        public string Body(string id)
        {
            var msg = DocumentSession.Load<Message>(id);
            if( msg != null)
            {
                return  msg.Body;
            }
            return string.Empty;
        }

        [HttpGet]
        public ActionResult Delete(string id)
        {
            var msg = DocumentSession.Load<Message>(id);
            if (msg != null)
            {
                DocumentSession.Delete(msg);
            }
            return RedirectToAction("Index");
        }

        [HttpGet]
        public ActionResult Subscribe(string id)
        {
            string username = string.Empty;
            string userEmailAddress = string.Empty;
            Message message = null;
            System.Threading.Tasks.ParallelOptions option = new ParallelOptions();
            option.MaxDegreeOfParallelism = System.Environment.ProcessorCount > 3 ? 2 : 1;

            username = CurrentUserName;
            Parallel.Invoke(option,
                            () => { userEmailAddress = GetEmailAddress(username); },
                            () => { message = DocumentSession.Load<Message>(id); }
                );


            ViewBag.ToAddress = message.To;
            ViewBag.SubscriberEmail = userEmailAddress;

            return View();
        }


        [HttpPost]
        public ActionResult Subscribe(FormCollection collection)
        {
            string emailAddress = collection["EmailAddress"];
            var sub = new Subscription
                          {
                              RealEmailAddress = emailAddress,
                              To = collection["ToAddress"].Replace("&lt;", "<").Replace("&gt;", ">"),
                              Username = CurrentUserName
                          };
            DocumentSession.Store(sub);

            // Store the collection's EmailAddress to session
            SetEmailAddress(emailAddress);

            return RedirectToAction("Index");
        }

        [HttpGet]
        public JsonResult IsSubscribed(string id)
        {
            var subscriptionsForCurrentUser =
                DocumentSession.Query<Subscription>().Where(s => s.Username == CurrentUserName);

            return new JsonResult
                       {
                           Data = subscriptionsForCurrentUser.Any(s => s.To == id),
                           JsonRequestBehavior = JsonRequestBehavior.AllowGet
                       };
        }


        private string _currentUserName;
        public string CurrentUserName
        {
            get
            {
                if (_currentUserName == null)
                {
                    _currentUserName = Request.LogonUserIdentity.Name;
                }
                return _currentUserName;
            }
        }

        private const string EmailAddressSessionKey = "CurrentUsersEmailAddress";
        private string GetEmailAddress(string username)
        {
            if (HttpContext.Session == null)
            {
                return string.Empty;
            }
            if (HttpContext.Session[EmailAddressSessionKey] == null)
            {
                var emailAddress = GetEmailAddressFromActiveDirectory(username);
                Session[EmailAddressSessionKey] = emailAddress;
                return emailAddress;
            }
            return Session[EmailAddressSessionKey].ToString();
        }
        private void SetEmailAddress(string emailAddress)
        {
            Session[EmailAddressSessionKey] = emailAddress;           
        }

        private const string EmailPropertyNameKey = "emailPropertyName";
        private const string DomainSuffixKey = "domainSuffix";

        private string GetEmailAddressFromActiveDirectory(string username)
        {
            var settings = (NameValueCollection)ConfigurationManager.GetSection("ActiveDirectorySettings");
            var emailPropertyName = settings[EmailPropertyNameKey];

            var userName = Environment.UserName;
            var domainName = Environment.UserDomainName;

            string ldapQueryFormat = @"LDAP://{0}.{1}/DC={0}, DC={1}";
            string filterFormat = @"(&(samAccountName={0})(objectCategory=person)(objectClass=user))";

            try
            {
                SearchResult result = null;
                string rootQuery = string.Format(ldapQueryFormat, domainName, settings[DomainSuffixKey]);
                using (var root = new DirectoryEntry(rootQuery))
                {
                    using (var searcher = new DirectorySearcher(root))
                    {

                        searcher.Filter = string.Format(filterFormat, userName);
                        result = searcher.FindOne();
                    }
                }
                var de = result.GetDirectoryEntry();

                return de != null ? de.Properties[emailPropertyName].Value.ToString() : string.Empty;
            }
            catch( Exception ex)
            {
                //Log the exception
            }

            return string.Empty;
        }

    
    }
}
